﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Windows.Forms;
using Lidgren.Network;
using Log;
using MirrorDriver;
using Model.LiveControl;
using Network;
using Network.Messages.LiveControl;
using Network.Messages.LiveControl.C2S;
using Network.Messages.LiveControl.S2C;
using Providers.Extensions;
using Providers.LiveControl.Server.FormsControl;
using Providers.LiveControl.Server.ScreenHelper;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;

namespace Providers.LiveControl.Server
{
    public class LiveControlProvider : Provider
    {
        public const int KeyeventKeyup = 2;
        public static int Mtu = 250;

        private static readonly object Locker = new object();

        private readonly Dictionary<IPEndPoint, PtrConnection> _dicPtr = new Dictionary<IPEndPoint, PtrConnection>();

        private readonly Dictionary<IPEndPoint, MessageEventArgs<RequestScreenshotMessage>> _dicScreenMessage =
            new Dictionary<IPEndPoint, MessageEventArgs<RequestScreenshotMessage>>();

        private readonly FormsControl.FormsControl _formsControl;
        private readonly GridNodeManager _gridNodeManager;
        private readonly ScreenShotHelper _screenShotHelper = new ScreenShotHelper();
        public uint ScreenshotCounter;

        public LiveControlProvider(NetworkPeer network)
            : base(network)
        {
            MirrorDriver = new DesktopMirror();
            DesktopChanges = new List<Rectangle>();
            Timer = new Stopwatch();
            _gridNodeManager = new GridNodeManager();
            //MirrorDriver.DesktopChange += MirrorDriver_DesktopChange;
            _formsControl = new FormsControl.FormsControl();
            _formsControl.CurrentFormChanged += _formsControl_CurrentFormChanged1;
            _formsControl.FormClosedEvent += _formsControl_FormClosedEvent;
            _formsControl.FormMinisizedEvent += _formsControl_FormMinisizedEvent;
            _formsControl.FormStatusUpdate += _formsControl_FormStatusUpdate;
        }

        public DesktopMirror MirrorDriver { get; set; }

        /// <summary>
        ///     Stores a list of Screen regions that have changed, to be optimized for later.
        /// </summary>
        private List<Rectangle> DesktopChanges { get; }

        private Stopwatch Timer { get; set; }

        private void _formsControl_CurrentFormChanged1(object sender, FormItemChangedArgs e)
        {
            if (e.OldConnection != null)
            {
                var message = new S2CTellClientYourControlBeRecoveredMessage();
                Network.SendMessage(message, e.OldConnection);
            }
            if (e.NewConnection != null)
            {
                var message = new S2CTellClientYouGetTheControl();
                Network.SendMessage(message, e.NewConnection);
            }
        }

        private void _formsControl_FormStatusUpdate(object sender, FormItem e)
        {
            var message = new S2CTellClientFormItemUpdate { FormItemModel = e.GetModel() };
            Network.SendMessage(message);
        }

        private void _formsControl_FormMinisizedEvent(object sender, FormItem e)
        {
            foreach (var netConnection in e.Connections)
            {
                var message = new S2CTellClientFormMinisizedMessage { FormItemModel = e.GetModel() };
                Network.SendMessage(message, netConnection);
            }

            
        }

        private void ReshowMinisizeForm(IntPtr ptr)
        {
            WindowApi.ShowWindow(ptr, WindowApi.ShowWindowCmd.SwShowNormal);
        }

        private void _formsControl_FormClosedEvent(object sender, FormItem e)
        {
            foreach (var netConnection in e.Connections)
            {
                var message = new S2CTellClientFormClosedMessage { FormItemModel = e.GetModel() };
                Network.SendMessage(message, netConnection);
            }
        }


        public void SendCursor(Cursor currentCursor)
        {
            foreach (var messageEventArgse in _dicScreenMessage.Values)
            {
                Network.SendMessage(new CursorMessage
                {
                    Cursor = currentCursor
                },
                    NetDeliveryMethod.ReliableOrdered,
                    3, messageEventArgse.Connection);
            }
        }

        public override void Heartbeat(float now, uint frameCounter)
        {
            // 10帧跳一次
            if (frameCounter % 20 != 0)
            {
                return;
            }

            if (Network.IsConnected)
            {
                _gridNodeManager?.SendScreens(Network, _dicScreenMessage);
            }
            _formsControl.Heartbeat(now, frameCounter);
            foreach (var netConnection in Network.Connections)
            {
                var message = new ServerStatusMessage
                {
                    ScreenCount = Screen.AllScreens.Length
                };

                Network.SendMessage(
                    message,
                    NetDeliveryMethod.ReliableOrdered,
                    3,
                    netConnection
                    );
            }
            foreach (var ptr in _dicPtr)
            {
                //当这个窗体被关或者被最小化的时候，回到全屏
                if (ptr.Value.Ptr > 0 &&
                    (!WindowApi.IsWindow(new IntPtr(ptr.Value.Ptr)) || WindowApi.IsIconic(new IntPtr(ptr.Value.Ptr))))
                {
                    var message = new ResponseCurrentProcPtr
                    {
                        Rect = new IdRect
                        {
                            Ptr = -1
                        },
                        ProcName = ""
                    };
                    Network.SendMessage(
                        message,
                        NetDeliveryMethod.ReliableOrdered,
                        3,
                        ptr.Value.Connection
                        );
                    var temp = ptr.Value;
                    temp.Ptr = -1;
                    _dicPtr[ptr.Key] = temp;
                }
            }
        }

        private void MirrorDriver_DesktopChange(object sender, DesktopMirror.DesktopChangeEventArgs e)
        {
            var rectangle = e.Region;
            DesktopChanges.Add(rectangle);
        }

        public override void RegisterMessageHandlers()
        {
            Network.RegisterMessageHandler<RequestScreenshotMessage>(OnRequestScreenshotMessageReceived);

            if (true)
            {
                //鼠标
                Network.RegisterMessageHandler<MouseDownMessage>(Client_MouseDown);
                Network.RegisterMessageHandler<MouseUpMessage>(Client_MouseUp);
                Network.RegisterMessageHandler<MouseClickMessage>(Client_OnMouseClick);
                Network.RegisterMessageHandler<MouseDoubleClickMessage>(Client_OnMouseDoubleClick);
                Network.RegisterMessageHandler<MouseMoveMessage>(Client_OnMouseMove);
                Network.RegisterMessageHandler<MouseScrollMessage>(Client_OnMouseScroll);

                Network.RegisterMessageHandler<GetWindowFormPointMessage>(On_GetWindowFormMessageRecived);
                //键盘
                Network.RegisterMessageHandler<KeyDownMessage>(Client_OnKeyDown);
                Network.RegisterMessageHandler<KeyUpMessage>(Client_OnKeyUp);
            }

            Network.RegisterMessageHandler<RequestClearRectMessage>(OnRequestClearRectRecived);
            Network.RegisterMessageHandler<RequestProccessListMessage>(OnRequestProccessList);
            Network.RegisterMessageHandler<RequsetScreenRectMessage>(OnRequestScreenRect);

            Network.RegisterMessageHandler<C2SConnectFormMessage>(RecieveConnectFormMessage);
            Network.RegisterMessageHandler<C2SRequestShareFormListMessage>(RecievedRequestShareFormListMessage);
            Network.RegisterMessageHandler<C2SRequestControlForceMessge>(RecievedRequestControlForceMessage);
            Network.RegisterMessageHandler<C2SRequestControlMessge>(RecievedRequestControlMessage);
            Network.RegisterMessageHandler<C2SResponseControlResultMessge>(RecievedResponseControlResultMessage);
            Network.RegisterMessageHandler<C2STellServerClientDisconnectMessage>(RecievedClientDisconnectedMessage);
            Network.RegisterMessageHandler<C2SReshowMinisizeFormMessage>(RecievedReshowMinisizeFormMessage);

            Network.RegisterMessageHandler<C2SChangeWindowStatusMessage>(RecievedChangeWindowStatusMessage);
        }

        private void RecievedChangeWindowStatusMessage(MessageEventArgs<C2SChangeWindowStatusMessage> obj)
        {
            ChangeWindowStatus(obj.Message);
        }

        private void ChangeWindowStatus(C2SChangeWindowStatusMessage objMessage)
        {
            IntPtr ptr = new IntPtr(objMessage.Ptr);
            switch (objMessage.Status)
            {
                case WindowShowType.Max:
                    WindowApi.ShowWindow(ptr, WindowApi.ShowWindowCmd.SwShowMaximized);
                    break;
                case WindowShowType.Nomal:
                    WindowApi.ShowWindow(ptr, WindowApi.ShowWindowCmd.SwShowNormal);
                    break;
                case WindowShowType.Top:
                    WindowApi.ShowWindow(ptr, WindowApi.ShowWindowCmd.SwShowNormal);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void RecievedReshowMinisizeFormMessage(MessageEventArgs<C2SReshowMinisizeFormMessage> obj)
        {
            ReshowMinisizeForm(obj.Message.FormItemModel.Ptr);
        }

        private void RecievedClientDisconnectedMessage(MessageEventArgs<C2STellServerClientDisconnectMessage> obj)
        {
           
            //_formsControl.DisConnectForm();
        }

        private void RecievedResponseControlResultMessage(MessageEventArgs<C2SResponseControlResultMessge> obj)
        {
            switch (obj.Message.Result)
            {
                case ResultType.Allow:
                    _formsControl.AcceptPreSetConnection();
                    break;
                case ResultType.Refuse:
                    var tMessage = new S2CRefuseControlApplyMessage
                    {
                        RefuseReason = obj.Message.RefuseReason
                    };
                    Network.SendMessage(tMessage, _formsControl.RefuseConnection());
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void RecievedRequestControlMessage(MessageEventArgs<C2SRequestControlMessge> obj)
        {
            var tMessage = new S2CRequestRecoverControlMessage
            {
                FlagForce = false
            };
            _formsControl.PreSetConnection(obj.Connection);

            var netConnection = _formsControl.GetCurrentConnection();
            if (netConnection != null)
            {
                Network.SendMessage(tMessage, netConnection);
            }
            else
            {
                _formsControl.AcceptPreSetConnection();
            }
        }

        private void RecievedRequestControlForceMessage(MessageEventArgs<C2SRequestControlForceMessge> obj)
        {
           
            _formsControl.PreSetConnection(obj.Connection);

            var tMessage = new S2CRequestRecoverControlMessage
            {
                FlagForce = true,
            };
            var netConnection = _formsControl.GetCurrentConnection();
            if (netConnection != null)
            {
                Network.SendMessage(tMessage, netConnection);
            }

            _formsControl.AcceptPreSetConnection();
        }

        private void RecievedRequestShareFormListMessage(MessageEventArgs<C2SRequestShareFormListMessage> obj)
        {
            var tMessage = new S2CResponseShareFormListMessage {FormItemModels = _formsControl.Models};
            Network.SendMessage(tMessage, obj.Connection);
        }

        private void RecieveConnectFormMessage(MessageEventArgs<C2SConnectFormMessage> obj)
        {
          var item =  _formsControl.ConnectForm(obj.Message.FormItemModel, obj.Connection);
            if (item.FlagMinisized)
            {
                ReshowMinisizeForm(item.Ptr);
            }
            WindowApi.SetForegroundWindow(item.Ptr);
        }

        private void OnRequestScreenRect(MessageEventArgs<RequsetScreenRectMessage> e)
        {
            var index = e.Message.ScreenIndex;
            var tMessage = new ResponseScreenRectMessage();

            index = Screen.AllScreens.Length - 1 < index ? 0 : index;
            tMessage.Bounds = Screen.AllScreens[index].Bounds;

            Network.SendMessage(tMessage, e.Connection);
        }

        private void OnRequestClearRectRecived(MessageEventArgs<RequestClearRectMessage> e)
        {
            var ptr = new IntPtr(e.Message.PtrNeedClear);
            WindowApi.ClearHighlight(ptr);
        }

        private void On_GetWindowFormMessageRecived(MessageEventArgs<GetWindowFormPointMessage> e)
        {
            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            var ptr = WindowApi.WindowFromPoint(absX, absY);
            var ret = WindowApi.GetRectByPtr(ptr);
            WindowApi.Highlight(ptr);
            _dicPtr[e.Connection.RemoteEndPoint] = new PtrConnection
            {
                Ptr = ptr.ToInt32(), Connection = e.Connection
            };

            var rectScreen = _screenShotHelper.GetRectangle(e.Message.ScreenIndex);
            OffsetRect(ret, rectScreen);

            Network.SendMessage(new ResponseCurrentProcPtr {Rect = ret, ProcName = ""}, NetDeliveryMethod.ReliableOrdered, 3, e.Connection);
        }

        private static void OffsetRect(IdRect ret, Rectangle rectScreen)
        {
            ret.Rect.Left -= rectScreen.X;
            ret.Rect.Right -= rectScreen.X;
            ret.Rect.Top -= rectScreen.Y;
            ret.Rect.Bottom -= rectScreen.Y;
        }

        private void OnRequestProccessList(MessageEventArgs<RequestProccessListMessage> e)
        {
            Network.SendMessage(new ResponseProccessListMessage {ProcList = WindowApi.GetProces()}, NetDeliveryMethod.ReliableOrdered, 3, e.Connection);

            Network.SendMessage(new ResponseRectListMessage {RectList = WindowApi.GetRects()}, NetDeliveryMethod.ReliableOrdered, 3, e.Connection);
        }


        private static void MapMouseEventParams(MouseEventBase messge, out int absX, out int absY, out int flag)
        {
            var boundes = Screen.AllScreens[messge.ScreenIndex].Bounds;
            absX = (int) (boundes.X + boundes.Width*messge.MouseEventArgs.RatioX);
            absY = (int) (boundes.Y + boundes.Height*messge.MouseEventArgs.RatioY);
            Cursor.Position = new Point(absX, absY);
            flag = messge.MouseEventArgs.BtnFlag;
        }

        /// <summary>
        ///     接收到请求屏幕消息
        /// </summary>
        /// <param name="e"></param>
        private void OnRequestScreenshotMessageReceived(MessageEventArgs<RequestScreenshotMessage> e)
        {
            if (_dicScreenMessage.ContainsKey(e.Connection.RemoteEndPoint))
            {
                //出现新关键帧或当前帧已经被解决了。
                if (_dicScreenMessage[e.Connection.RemoteEndPoint].Message.Resolve || e.Message.FlagFirstFrame)
                {
                    _dicScreenMessage[e.Connection.RemoteEndPoint] = e;
                }
                else
                {
                    _dicScreenMessage[e.Connection.RemoteEndPoint].Message.Id = e.Message.Id;
                }
            }
            else
            {
                _dicScreenMessage[e.Connection.RemoteEndPoint] = e;
            }
        }


        private void DealWithScreenShotMessage(MessageEventArgs<RequestScreenshotMessage> e, IList<Rectangle> changesCopy)
        {
            var procId = e.Message.Id;

            if (!DoesMirrorDriverExist())
            {
                AskIntallDemoforgeAddExit();
            }
            try
            {
                UpdateConnectionInfo(e);

                if (MirrorDriver.State != DesktopMirror.MirrorState.Running)
                {
                    // Most likely first time
                    // Start the mirror driver
                    MirrorDriver.Load();

                    MirrorDriver.Connect();
                    MirrorDriver.Start();

                    DealWithFirstFrame(e);
                }
                else if (MirrorDriver.State == DesktopMirror.MirrorState.Running)
                {
                    if (e.Message.FlagFirstFrame)
                    {
                        DealWithFirstFrame(e);
                    }
                    else
                    {
                        //Trace.WriteLine("Received RequestScreenshotMessage.");
                        var screenshot = _screenShotHelper[e.Message.ScreenIndex];
                        var regionsStore = changesCopy;
                        var rectScreen = _screenShotHelper.GetRectangle(e.Message.ScreenIndex);

                        if (procId > 0)
                        {
                            var rect = WindowApi.GetRect(procId);
                            regionsStore = Intersect(regionsStore, rect, rectScreen);

                            OffsetRect(rect, rectScreen);

                            Network.SendMessage(new ResponseRectChangeMessage {Rect = rect}, NetDeliveryMethod.ReliableOrdered, 3, e.Connection);
                        }
                        else
                        {
                            regionsStore = Intersect(regionsStore, rectScreen);
                        }

                        if (regionsStore.Count == 0)
                        {
                            Network.SendMessage(new ResponseEmptyScreenshotMessage(), NetDeliveryMethod.ReliableOrdered, 0, e.Connection);
                            return;
                        }

                        foreach (var t in regionsStore)
                        {
                            if (t.IsEmpty) continue;
                            t.Offset(-rectScreen.X, -rectScreen.Y);
                            Bitmap regionShot = null;

                            try
                            {
                                regionShot = screenshot.Clone(t, PixelFormat.Format16bppRgb565);
                            }
                            catch (OutOfMemoryException)
                            {
                                Trace.WriteLine("OutOfMemoryException");
                            }

                            var stream = new MemoryStream();
                            regionShot?.Save(stream, ImageFormat.Png);
                            SendFragmentedBitmap(stream.ToArray(), t, e.Connection);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 比如连接断了什么的，既然没有连接了，就把镜像关了吧，省点资源。
                //if (!Network.IsConnected)
                //{
                //    MirrorDriver.Unload();
                //}
                C.LogtoTextDebug("catch", "DealWithScreenShotMessage_Bug", ex.Message);
                //Trace.WriteLine(ex.Message);
            }
        }

        /// <summary>
        ///     发送全屏截屏，并构建并重置（清空）该连接的变化区域列表
        /// </summary>
        /// <param name="e"></param>
        private void DealWithFirstFrame(MessageEventArgs<RequestScreenshotMessage> e)
        {
            var screenshot = _screenShotHelper[e.Message.ScreenIndex];
            var stream = new MemoryStream();
            screenshot.Save(stream, ImageFormat.Png);

            var index = e.Message.ScreenIndex;
            var bounds = _screenShotHelper.GetRectangle(index);
            bounds.Location = new Point(0, 0);
            SendFragmentedBitmap(stream.ToArray(), bounds, e.Connection);
        }

        /// <summary>
        ///     更新连接的当前信息
        /// </summary>
        /// <param name="e"></param>
        private void UpdateConnectionInfo(MessageEventArgs<RequestScreenshotMessage> e)
        {
            if (_dicPtr.ContainsKey(e.Connection.RemoteEndPoint))
            {
                var temp = _dicPtr[e.Connection.RemoteEndPoint];
                temp.Ptr = e.Message.Id;
                temp.Connection = e.Connection;
                _dicPtr[e.Connection.RemoteEndPoint] = temp;
            }
            else
            {
                _dicPtr[e.Connection.RemoteEndPoint] = new PtrConnection
                {
                    Ptr = e.Message.Id, Connection = e.Connection
                };
            }
        }

        /// <summary>
        ///     通知下载安装dfmirage，并退出服务程序
        /// </summary>
        private static void AskIntallDemoforgeAddExit()
        {
            var dialogResult = MessageBox.Show("你没有安装demoforge镜像驱动器，或者你在安装后还没有重新启动您的计算机。没有镜像驱动程序，此应用程序将无法正常工作。镜像驱动程序负责通知任何改变屏幕区域的应用，通过这些改变屏幕区域应用位图。按“是”直接下载驱动程序（您之后仍然需要安装）. 你可以浏览以下网站: http://www.demoforge.com/dfmirage.htm", "M镜像驱动器没有安装", MessageBoxButtons.YesNo, MessageBoxIcon.Error);

            if (dialogResult == DialogResult.Yes)
            {
                Process.Start("http://www.demoforge.com/tightvnc/dfmirage-setup-2.0.301.exe");
            }

            MessageBox.Show("现在退出程序.", "缺少必要组件", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Application.Exit();
        }

        private List<Rectangle> Intersect(IList<Rectangle> regionsStore, Rectangle rectBoudle)
        {
            var ret = new List<Rectangle>();
            foreach (var rectangle in regionsStore)
            {
                if (rectBoudle.Contains(rectangle))
                {
                    ret.Add(rectangle);
                    continue;
                }
                if (rectBoudle.IntersectsWith(rectangle))
                {
                    var interSect = Rectangle.Intersect(rectBoudle, rectangle);
                    ret.Add(interSect);
                }
            }
            return ret;
        }

        private List<Rectangle> Intersect(IList<Rectangle> regionsStore, IdRect rect, Rectangle rectScreenBoudle)
        {
            var rectBoudle = new Rectangle(rect.Rect.Left, rect.Rect.Top, rect.Rect.Right - rect.Rect.Left, rect.Rect.Bottom - rect.Rect.Top);
            var boudle = Rectangle.Intersect(rectBoudle, rectScreenBoudle);
            return Intersect(regionsStore, boudle);
        }

        private void SendFragmentedBitmap(byte[] bitmapBytes, Rectangle region, NetConnection connection = null)
        {
            // Send ResponseBeginScreenshotMessage
            var beginMessage = new ResponseBeginScreenshotMessage
            {
                Number = ++ScreenshotCounter, Region = region, FinalLength = bitmapBytes.Length
            };

            Network.SendMessage(beginMessage, NetDeliveryMethod.ReliableOrdered, 0, connection);

            // Send ResponseScreenshotMessage

            // We don't want to send a 300 KB image - we want to make each packet Mtu bytes
            // int numFragments = (bitmapBytes.Length / Mtu) + 1;
            var numFragments = (int) Math.Floor(bitmapBytes.Length/(decimal) Mtu) + 1;

            for (var i = 0; i < numFragments; i++)
            {
                var message = new ResponseScreenshotMessage();

                byte[] regionFragmentBuffer = null;

                if (i != numFragments - 1 && i < numFragments)
                {
                    regionFragmentBuffer = new byte[Mtu];
                    Buffer.BlockCopy(bitmapBytes, i*Mtu, regionFragmentBuffer, 0, Mtu);
                }
                else if (i == numFragments - 1 || numFragments == 1)
                {
                    var bytesLeft = bitmapBytes.Length%Mtu;
                    regionFragmentBuffer = new byte[bytesLeft];
                    Buffer.BlockCopy(bitmapBytes, i*Mtu, regionFragmentBuffer, 0, bytesLeft);
                }
                else if (i == numFragments - 1)
                {
                    break;
                }

                if (regionFragmentBuffer == null)
                    Debugger.Break();

                message.Number = ScreenshotCounter;
                message.Image = regionFragmentBuffer;
                message.SendIndex = i <= 0 ? 0 : i;
                Network.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 0, connection);
                Trace.WriteLine($"Sent screenshot #{ScreenshotCounter}, fragment #{i} of {numFragments} ({message.Image.Length.ToKilobytes()} KB).");
            }

            Network.SendMessage(new ResponseEndScreenshotMessage {Number = ScreenshotCounter}, connection);
            //Trace.WriteLine(
            //    $"Completed send of screenshot #{ScreenshotCounter}, Size: {bitmapBytes.Length.ToKilobytes()} KB");
        }

        private static float GetTotalScreenshotsKb(List<Screenshot> screenshots)
        {
            var total = 0f;
            screenshots.ForEach(x => { total += x.Image.Length.ToKilobytes(); });
            return total;
        }

        /// <summary>
        ///     Combines intersecting rectangles to reduce redundant sends.
        /// </summary>
        /// <returns></returns>
        public IList<Rectangle> GetOptimizedRectangleRegions()
        {
            List<Rectangle> desktopChangesCopy;
            lock (Locker)
            {
                desktopChangesCopy = new List<Rectangle>(DesktopChanges);
                DesktopChanges.Clear();
            }

            return desktopChangesCopy;
        }

        public event EventHandler<DesktopChangedEventArgs> OnDesktopChanged;

        public bool DoesMirrorDriverExist()
        {
            return MirrorDriver.DriverExists();
        }

        public void SendShutdownKonwledge()
        {
            Network.SendMessage(new KnowladgeServerMachineShutDown());
        }

        private struct PtrConnection
        {
            public int Ptr;
            public NetConnection Connection;
        }

        #region 还原键盘鼠标事件

        private void Client_OnKeyUp(MessageEventArgs<KeyUpMessage> obj)
        {
            if (!_formsControl.CheckAllowOperation(obj.Connection))
                return;

            var key = obj.Message.KeyEventArgs.KeyData;
            WindowApi.keybd_event(key, 0, KeyeventKeyup, 0);
        }

        private void Client_OnKeyDown(MessageEventArgs<KeyDownMessage> obj)
        {
            if (!_formsControl.CheckAllowOperation(obj.Connection))
                return;

            var key = obj.Message.KeyEventArgs.KeyData;
            WindowApi.keybd_event(key, 0, 0, 0);
        }

        private void Client_OnMouseScroll(MessageEventArgs<MouseScrollMessage> e)
        {
            if (!_formsControl.CheckAllowOperation(e.Connection))
                return;
            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            WindowApi.mouse_event(flag, 0, 0, e.Message.MouseEventArgs.Delta, 0);
        }

        private void Client_OnMouseMove(MessageEventArgs<MouseMoveMessage> e)
        {
            if (!_formsControl.CheckAllowOperation(e.Connection))
                return;

            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            Network.SendEventMessage(new ResponseTime {StartTime = e.Message.Now}, e.Connection);
        }

        /// <summary>
        /// </summary>
        /// <param name="e"></param>
        private void Client_OnMouseClick(MessageEventArgs<MouseClickMessage> e)
        {
            if (!_formsControl.CheckAllowOperation(e.Connection))
                return;

            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            WindowApi.mouse_event(flag, 0, 0, 0, 0);
        }

        private void Client_MouseUp(MessageEventArgs<MouseUpMessage> e)
        {
            if (!_formsControl.CheckAllowOperation(e.Connection))
                return;

            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            WindowApi.mouse_event(flag, 0, 0, 0, 0);
        }

        private void Client_MouseDown(MessageEventArgs<MouseDownMessage> e)
        {
            if (!_formsControl.CheckAllowOperation(e.Connection))
            {
                S2CRefuseControlMessage tMessage = new S2CRefuseControlMessage {MouseType = MouseType.MouseDown};
                Network.SendMessage(tMessage, e.Connection);
                return;
            }
            int absX, absY, flag;
            MapMouseEventParams(e.Message, out absX, out absY, out flag);

            WindowApi.mouse_event(flag, 0, 0, 0, 0);
        }

        private void Client_OnMouseDoubleClick(MessageEventArgs<MouseDoubleClickMessage> obj)
        {
            if (!_formsControl.CheckAllowOperation(obj.Connection))
            {
                //if (obj.Message.MouseEventArgs.IsLeft)
                //{
                    S2CRefuseControlMessage tMessage = new S2CRefuseControlMessage { MouseType = MouseType.DoubleClick };
                    Network.SendMessage(tMessage, obj.Connection);
                //}
               
                return;
            }

            // 两次单击就是双击，所以双击不应该触发鼠标事件，不然会有重复，但可以做为条件开关
        }

        #endregion
    }
}